<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      let name = 'zs';
      let obj = {
        name: 'lisi',
      };
      function getName(a, b, c) {
        console.log(this.name);
        console.log(a, b, c);
      }
      Function.prototype.myCall = function (context) {
        // 这里的this就是调用的方法
        if (typeof this !== 'function') {
          throw new Error('type error');
        }
        context = context || window;
        // 截取参数
        let args = [...arguments].slice(1);
        // 在obj对象里面新增调用方法
        context.fn = this;
        // 调用obj里面的方法fn
        let result = context.fn(...args);
        // 删除obj里面新增的方法
        delete context.fn;
        return result;
      };
      getName.myCall(obj, 1, 2, 3);

      Function.prototype.myApply = function (context) {
        // 这里的this就是调用的方法
        if (typeof this !== 'function') {
          throw new Error('type error');
        }
        context = context || window;
        // 截取参数
        let args = [...arguments].slice(1);
        // 在obj对象里面新增调用方法
        context.fn = this;
        // 调用obj里面的方法fn
        let result = context.fn(args);
        // 删除obj里面新增的方法
        delete context.fn;
        return result;
      };
      getName.myApply(obj, 1, 2, 3);

      Function.prototype.myBind = function (context) {
        if (typeof this !== 'function') {
          throw new Error('Error');
        }
        const args = [...arguments].slice(1),
          fn = this;
        return function Fn() {
          return fn.apply(this instanceof Fn ? this : context, args.concat(...arguments));
        };
      };

      Function.prototype.myCall = function (context) {
        if (typeof this !== 'function') {
          throw new Error('Error');
        }
        let args = [...arguments].slice(1);
        context = context || window;
        context.fn = this;
        let result = context.fn(...args);
        delete context.fn;
        return result;
      };
    </script>
  </body>
</html>
